#pragma once
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <future>
#include <atomic>

class ThreadPool {
public:
	ThreadPool(size_t threads = std::thread::hardware_concurrency())
		:stop(false) 
	{
		for (size_t i = 0; i < threads; i++) {
			workers.emplace_back([this] {
				for (;;) {
					Task task;
					{
						std::unique_lock<std::mutex> lock(this->queue_mutex);
						condition.wait(lock, [this] {
							return stop || !tasks.empty();
							});
						if (stop && tasks.empty())return;//线程池关闭且任务为空，线程退出
						task = std::move(tasks.front());
						tasks.pop();
					}
					task();
				}
			});
		}
	}
	ThreadPool(const ThreadPool&) = delete;
	ThreadPool& operator=(const ThreadPool&) = delete;

	~ThreadPool() {
		{
			std::unique_lock<std::mutex> lock(queue_mutex);
			stop = true;
		}
		condition.notify_all();
		for (std::thread& worker : workers) {
            worker.join();
		}
	}
	template<class F, class... Args>
	auto submit(F&& f, Args&&... args) 
		->std::future<typename std::result_of<F(Args...)>::type>
	{
		using return_type = typename std::result_of<F(Args...)>::type;

		// 使用 packaged_task 封装函数和参数
		auto task_ptr = std::make_shared<std::packaged_task<return_type()>>(
			std::bind(std::forward<F>(f), std::forward<Args>(args)...)
		);

		{
			std::unique_lock<std::mutex> lock(queue_mutex);
			if (stop)
				throw std::runtime_error("submit on stopped ThreadPool");
			// 将任务包装为 void() 类型，加入任务队列
			tasks.emplace([task_ptr]() { (*task_ptr)(); });
		}

		condition.notify_one(); // 通知一个工作线程处理任务
		return task_ptr->get_future(); // 返回 future 对象用于获取结果
	}

private:
	using Task = std::function<void()>;
	std::vector<std::thread> workers;//负责保存所有工作线程，这些线程会从任务队列中不断拉取任务执行。
	std::queue<Task> tasks;

	std::mutex queue_mutex; //保护任务队列
	std::condition_variable condition; //条件变量
	/*
	如果没有任务，不希望线程一直在空转（死循环浪费CPU），
	所以用条件变量让它们睡觉，直到：
	有任务进来了（notify_one() 唤醒）
	或线程池准备停止（stop = true）
	*/
	std::atomic<bool> stop; //是否停止

};